package com.zt.bus.wx.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import net.sf.json.JSONObject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.monkeyk.os.domain.oauth.AccessToken;
import com.zt.bus.constant.BusConstant;
import com.zt.bus.wx.service.WxService;
import com.zt.bus.wx.util.ReturnModel;
import com.zt.bus.wx.util.WxUtil;
import com.zt.servlet.ReqBean;
import com.zt.servlet.RequestAttribute;
import com.zt.servlet.Response;
import com.zt.system.model.BusinessException;
import com.zt.user.api.UserApi;
import com.zt.user.user.model.User;
import com.zt.util.PropertiesUtil;
import com.zt.util.StringUtil;

@Controller
@RequestMapping(value = "/wx")
public class WxMpController {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected WxMpConfigStorage configStorage;
    @Autowired
    protected WxMpService wxMpService;
    @Autowired
    protected WxService wxService;

    /**
     * 微信公众号webservice主服务接口，提供与微信服务器的信息交互
     * 
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/access", method = RequestMethod.GET)
    @ResponseBody
    public void wechatCore(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);

        String signature = request.getParameter("signature");
        String nonce = request.getParameter("nonce");
        String timestamp = request.getParameter("timestamp");

        if (!this.wxMpService.checkSignature(timestamp, nonce, signature)) {
            // 消息签名不正确，说明不是公众平台发过来的消息
            response.getWriter().println("非法请求");
            return;
        }

        String echoStr = request.getParameter("echostr");
        if (StringUtils.isNotBlank(echoStr)) {
            // 说明是一个仅仅用来验证的请求，回显echostr
            String echoStrOut = String.copyValueOf(echoStr.toCharArray());
            response.getWriter().println(echoStrOut);
            return;
        }

        String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ? "raw" : request
                .getParameter("encrypt_type");

        if ("raw".equals(encryptType)) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
            WxMpXmlOutMessage outMessage = this.wxService.route(inMessage);
            response.getWriter().write(outMessage.toXml());
            return;
        }

        if ("aes".equals(encryptType)) {
            // 是aes加密的消息
            String msgSignature = request.getParameter("msg_signature");
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), this.configStorage,
                    timestamp, nonce, msgSignature);
            this.logger.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
            WxMpXmlOutMessage outMessage = this.wxService.route(inMessage);
            this.logger.info(response.toString());
            response.getWriter().write(outMessage.toEncryptedXml(this.configStorage));
            return;
        }

        response.getWriter().println("不可识别的加密类型");
        return;
    }

    /**
     * 通过code获得基本用户信息 详情请见:
     * http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html
     * 
     * @param response
     * @param code
     *            code zh_CN, zh_TW, en
     */
    @RequestMapping(value = "/index")
	public String index(HttpServletRequest request, HttpServletResponse response,RedirectAttributes redirectAttributes,
						@RequestParam(value = "code") String code) throws ServletException, IOException {
        ReturnModel returnModel = new ReturnModel();
        try {
            String openId = getCookie(request,"openId");
//            openId = "o0UQTwfJTCoGazbasKcYGqX3LTTY"; //zlh
            openId = "o0UQTwb-yBtjUvkbhGi5IIXMvbsk"; //wmx
            if(StringUtil.isEmpty(openId)){
                WxMpOAuth2AccessToken accessToken = this.wxMpService.oauth2getAccessToken(code);
                WxMpUser wxMpUser = this.wxMpService.getUserService()
                        .userInfo(accessToken.getOpenId(), BusConstant.Wx.LANG);
                returnModel.setResult(true);
                returnModel.setDatum(wxMpUser);
                openId = wxMpUser.getOpenId();
                JSONObject userInfoJson = WxUtil.renderJson(response, returnModel);
                System.out.println("zlh:" + userInfoJson);
            }
			// 获取绑定的用户
			User user = UserApi.getUserByOpenId(openId);
			if (user != null) {
				// 获取授权
				AccessToken oauth2Token = UserApi.retrievePasswordAccessToken(user.getPhone());
				//response.addCookie(new Cookie("access_token", oauth2Token.tokenId()));
				redirectAttributes.addAttribute("access_token", oauth2Token.tokenId());
			}
			//response.addCookie(new Cookie("openId", openId));
			redirectAttributes.addAttribute("openId", openId);
			return "redirect:/weixin/cookie.html";
			//return redirect;
        } catch (WxErrorException e) {
            returnModel.setResult(false);
            returnModel.setReason(e.getError().toString());
            WxUtil.renderString(response, returnModel);
            this.logger.error(e.getError().toString());
				return "redirect:/403.do";
        }

	}

    /**
     * 通过openid获得基本用户信息 详情请见:
     * http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html
     * 
     * @param response
     * @param openId
     *            openId
     * @param lang
     *            zh_CN, zh_TW, en
     */
    @RequestMapping(value = "/getUserInfo")
    public WxMpUser getUserInfo(HttpServletResponse response,
            @RequestParam(value = BusConstant.Wx.OPEN_ID) String openId, @RequestParam(value = "lang") String lang) {
        ReturnModel returnModel = new ReturnModel();
        WxMpUser wxMpUser = null;
        try {
            wxMpUser = this.wxMpService.getUserService().userInfo(openId, lang);
            returnModel.setResult(true);
            returnModel.setDatum(wxMpUser);
            WxUtil.renderString(response, returnModel);
        } catch (WxErrorException e) {
            returnModel.setResult(false);
            returnModel.setReason(e.getError().toString());
            WxUtil.renderString(response, returnModel);
            this.logger.error(e.getError().toString());
        }
        return wxMpUser;
    }

    /**
     * 用户注册
     * 
     * @param reqBean
     * @return 新的access_token
     */
    @RequestMapping(value = "/register")
    @ResponseBody
    public JSONObject register(@RequestAttribute(ReqBean.NAME) ReqBean reqBean) {
        String openId = reqBean.getInfo("openId");
        String phone = reqBean.getInfo("phone");
        String captcha = reqBean.getInfo("captcha");
        if (StringUtil.isEmpty(openId) || StringUtil.isEmpty(phone) || StringUtil.isEmpty(captcha)) {
            throw new BusinessException("获取注册参数失败！");
        }
        User user = UserApi.wxRegister(openId, phone, captcha);
        JSONObject o = user.toJSONObject();
        AccessToken oauth2Token = UserApi.retrievePasswordAccessToken(user.getPhone());
        o.put("access_token", oauth2Token.tokenId());
        return Response.response(o);
    }
    
    /**
     * 
     * @param reqBean
     * @return
     */
    @RequestMapping(value = "/getRegisterUser")
    @ResponseBody
    public JSONObject getRegisterUser(@RequestAttribute(ReqBean.NAME) ReqBean reqBean) {
        User user = null;
        String openId = reqBean.getInfo("openId");
        if(StringUtil.isNotEmpty(openId)){
            user = UserApi.getUserByOpenId(openId);
            JSONObject o = user.toJSONObject();
            AccessToken oauth2Token = UserApi.retrievePasswordAccessToken(user.getPhone());
            o.put("access_token", oauth2Token.tokenId());
            return Response.response(o);
        }
        return Response.responseError("");
    }

    /**
     * 用code换取oauth2的openid 详情请见:
     * http://mp.weixin.qq.com/wiki/1/8a5ce6257f1d3b2afb20f83e72b72ce9.html
     * 
     * @param response
     * @param code
     *            code
     */
    @RequestMapping(value = "/getOpenid")
    public void getOpenid(HttpServletResponse response, @RequestParam(value = "code") String code) {
        ReturnModel returnModel = new ReturnModel();
        WxMpOAuth2AccessToken accessToken;
        try {
            accessToken = this.wxMpService.oauth2getAccessToken(code);
            returnModel.setResult(true);
            returnModel.setDatum(accessToken.getOpenId());
            WxUtil.renderString(response, returnModel);
        } catch (WxErrorException e) {
            returnModel.setResult(false);
            returnModel.setReason(e.getError().toString());
            WxUtil.renderString(response, returnModel);
            this.logger.error(e.getError().toString());
        }
    }
    
    @RequestMapping(value = "/setting")
    @ResponseBody
    public JSONObject setting(@RequestAttribute(ReqBean.NAME) ReqBean reqBean) {
    	JSONObject setting = new JSONObject();
    	setting.put("appId", PropertiesUtil.getProperty("wx.appId"));
    	String ucPath = PropertiesUtil.getProperty("user.center.path");
    	setting.put("imgCaptchaUrl", ucPath + PropertiesUtil.getProperty("user.center.imgCaptchaUrl"));
    	setting.put("smsCaptchaUrl", ucPath + PropertiesUtil.getProperty("user.center.smsCaptchaUrl"));
    	return Response.responseSuccess(setting);
    }
    
    /**
     * 获到jsapi签名信息
     * @param reqBean
     * @return
     */
    @RequestMapping(value = "/jsapiSignature")
    @ResponseBody
    public JSONObject jsapiSignature(@RequestAttribute(ReqBean.NAME) ReqBean reqBean) {
        WxJsapiSignature jsapiSignature;
        try {
            jsapiSignature = this.wxMpService.createJsapiSignature(reqBean.getInfo("url"));
            return Response.responseSuccess(jsapiSignature);
        } catch (WxErrorException e) {
            this.logger.error(e.getError().toString());
        }
        return Response.responseError("");
    }
    
    private String getCookie(HttpServletRequest request,String key){
        Cookie[] cookies = request.getCookies();
        try {
            for(Cookie c :cookies ){
                if(c.getName().equals(key)){
                    return c.getValue().toString().trim();
                }
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }
}
